﻿using ExcelFileMonitor.NPOI;
using ExcelFileMonitor.NPOI.Models;
using ExcelFileMonitor.NPOI.Services;
using LPLS.Commons.LogOP;
using Microsoft.Extensions.Logging;

namespace TestProject
{
    internal class Program
    {
        //static void Main(string[] args)
        //{
        //    Console.WriteLine("Hello, World!");
        //    LogHelper.Information("应用程序启动");

        //    LogHelper.CloseAndFlush();

        //    Console.ReadKey();
        //}


        private static IExcelFileWatcher _watcher;
        private static ILogger<Program> _logger;
        private static bool _isRunning = true;

        static async Task Main(string[] args)
        {
            Console.WriteLine("Excel文件监控系统 - 持续监听版本");
            Console.WriteLine("===========================================");

            // 创建服务容器
            var serviceProvider = BuildServiceProvider();
            _logger = serviceProvider.GetService<ILogger<Program>>();

            try
            {
                // 加载配置
                var config = ConfigurationLoader.LoadConfig();
                _watcher = serviceProvider.GetService<IExcelFileWatcher>();

                // 订阅事件
                _watcher.FileDetected += OnFileDetected;
                _watcher.ErrorOccurred += OnErrorOccurred;
                _watcher.StatusChanged += OnStatusChanged;

                // 启动监控
                await _watcher.StartWatchingAsync();

                Console.WriteLine($"监控根路径: {config.RootMonitorPath}");
                Console.WriteLine($"支持的文件扩展名: {string.Join(", ", config.FileExtensions)}");
                Console.WriteLine("系统已启动并开始持续监听...");
                Console.WriteLine("命令:");
                Console.WriteLine("  s - 显示状态");
                Console.WriteLine("  r - 重新扫描文件");
                Console.WriteLine("  c - 清除控制台");
                Console.WriteLine("  q - 退出");
                Console.WriteLine("===========================================");

                // 注册Ctrl+C事件
                Console.CancelKeyPress += OnCancelKeyPress;

                // 命令处理循环
                await ProcessCommandsAsync();
            }
            catch (Exception ex)
            {
                _logger?.LogError(ex, "应用程序启动失败");
                Console.WriteLine($"应用程序启动失败: {ex.Message}");
            }
            finally
            {
                await CleanupAsync();
                serviceProvider?.Dispose();
            }
        }

        private static async Task ProcessCommandsAsync()
        {
            while (_isRunning)
            {
                try
                {
                    if (Console.KeyAvailable)
                    {
                        var key = Console.ReadKey(intercept: true);
                        switch (key.KeyChar)
                        {
                            case 's':
                                ShowStatus(_watcher);
                                break;
                            case 'r':
                                Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] 重新扫描文件中...");
                                await _watcher.ScanExistingFilesAsync();
                                break;
                            case 'c':
                                Console.Clear();
                                Console.WriteLine("控制台已清除，继续监听...");
                                break;
                            case 'q':
                                Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] 正在退出...");
                                _isRunning = false;
                                break;
                        }
                    }

                    // 短暂休眠以减少CPU使用
                    await Task.Delay(100);
                }
                catch (Exception ex)
                {
                    // 命令处理异常，记录但继续运行
                    _logger?.LogError(ex, "命令处理异常");
                    Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] 命令处理异常: {ex.Message}");
                }
            }
        }

        private static void OnFileDetected(object sender, ExcelFileEvent e)
        {
            try
            {
                // 使用try-catch确保单个文件处理异常不影响整体
                ProcessFileEvent(e);
            }
            catch (Exception ex)
            {
                // 记录错误但继续运行
                _logger?.LogError(ex, "处理文件事件时发生异常: {FilePath}", e.FilePath);
                Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] 处理文件事件异常: {ex.Message}");
            }
        }

        private static void ProcessFileEvent(ExcelFileEvent e)
        {
            var timestamp = DateTime.Now.ToString("HH:mm:ss");

            switch (e.EventType)
            {
                case FileEventType.Created:
                    Console.WriteLine($"[{timestamp}] 🆕 新增Excel文件:");
                    break;
                case FileEventType.Modified:
                    Console.WriteLine($"[{timestamp}] 📝 修改Excel文件:");
                    break;
                case FileEventType.Deleted:
                    Console.WriteLine($"[{timestamp}] 🗑️  删除Excel文件:");
                    break;
                case FileEventType.Renamed:
                    Console.WriteLine($"[{timestamp}] 🔄 重命名Excel文件:");
                    break;
                case FileEventType.Error:
                    Console.WriteLine($"[{timestamp}] ❌ 文件错误:");
                    break;
            }

            Console.WriteLine($"     文件: {e.FileName}");
            Console.WriteLine($"     路径: {e.FilePath}");

            if (e.FileSize > 0)
            {
                Console.WriteLine($"     大小: {FormatFileSize(e.FileSize)}");
            }

            if (e.LastWriteTime != DateTime.MinValue)
            {
                Console.WriteLine($"     修改: {e.LastWriteTime:yyyy-MM-dd HH:mm:ss}");
            }

            if (e.Error != null)
            {
                Console.WriteLine($"     ⚠️  错误: {e.Error.Message}");
            }

            Console.WriteLine();

            // 在这里调用您自己的Excel处理逻辑
            // 使用try-catch包装您的处理代码，确保异常不会影响监控
            try
            {
                ProcessExcelFileWithRetry(e.FilePath);
            }
            catch (Exception ex)
            {
                // 记录错误但继续处理其他文件
                _logger?.LogError(ex, "处理Excel文件失败: {FilePath}", e.FilePath);
                Console.WriteLine($"[{timestamp}] ⚠️  处理Excel文件失败: {ex.Message}");
            }
        }

        private static async void ProcessExcelFileWithRetry(string filePath)
        {
            const int maxRetries = 2;
            const int retryDelayMs = 1000;

            for (int attempt = 1; attempt <= maxRetries; attempt++)
            {
                try
                {
                    // 调用您自己的Excel处理逻辑
                    await YourExcelProcessor.ProcessExcelFileAsync(filePath);

                    Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] ✅ 成功处理文件: {System.IO.Path.GetFileName(filePath)}");
                    return; // 成功则退出
                }
                catch (System.IO.IOException ioEx) when (ioEx.Message.Contains("正由另一进程使用") && attempt < maxRetries)
                {
                    // 文件被占用，重试
                    Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] ⏳ 文件被占用，{retryDelayMs}ms后重试 ({attempt}/{maxRetries}): {System.IO.Path.GetFileName(filePath)}");
                    await Task.Delay(retryDelayMs);
                }
                catch (Exception ex) when (attempt < maxRetries)
                {
                    // 其他异常，重试
                    Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] ⚠️  处理异常，{retryDelayMs}ms后重试 ({attempt}/{maxRetries}): {ex.Message}");
                    await Task.Delay(retryDelayMs);
                }
            }

            // 所有重试都失败
            Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] ❌ 处理文件失败(已达最大重试次数): {System.IO.Path.GetFileName(filePath)}");
        }

    }
}
































/*


   "SqlServer1": {
      "ConnectionString": "Server=.;Database=TestDB1;User Id=sa;Password=123456;",
      "DbType": "SQLServer",
      "IsCodeFirst": true
    },
    "SqlServer2": {
      "ConnectionString": "Server=.;Database=TestDB2;User Id=sa;Password=123456;",
      "DbType": "SQLServer",
      "IsCodeFirst": false
    },
    "MySql1": {
      "ConnectionString": "Server=localhost;Database=TestDB1;Uid=root;Pwd=123456;",
      "DbType": "MySql",
      "IsCodeFirst": true
    },
    "MySql2": {
      "ConnectionString": "Server=localhost;Database=TestDB2;Uid=root;Pwd=123456;",
      "DbType": "MySql",
      "IsCodeFirst": false
    },
    "Sqlite1": {
      "ConnectionString": "Data Source=TestDB1.db;Version=3;",
      "DbType": "SQLite",
      "IsCodeFirst": true
    },
    "Sqlite2": {
      "ConnectionString": "Data Source=TestDB2.db;Version=3;",
      "DbType": "SQLite",
      "IsCodeFirst": false
*/